package com.example.utils.weixin;


import com.example.utils.HttpClient;
import com.github.wxpay.sdk.WXPayUtil;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.converters.DateConverter;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class WeixinPayUtils {

    /**
     * 发起支付请求，并生成支付二维码链接
     *
     * @param callbackUrl
     * @param app_id
     * @param mch_id
     * @param api_key
     * @param out_trade_no
     * @param total_fee
     * @param body
     * @return
     */
    public static WeixinPayResult createNative(String callbackUrl, String app_id, String mch_id, String api_key, String out_trade_no, Integer total_fee, String body) {
        //1.参数封装
        //下面的参数可以通过封装一个实体类的bean对象，同时返回的结果，也可以封装的一个bean对象
        Map param = new HashMap();
        param.put("appid", app_id);//公众账号ID
        param.put("mch_id", mch_id);//商户
        param.put("nonce_str", WXPayUtil.generateNonceStr());//随机字符串
        param.put("body", body);
        param.put("out_trade_no", out_trade_no);//交易订单号（是由系统内部来生成）
        param.put("total_fee", total_fee.toString());//金额（分）
        param.put("spbill_create_ip", "127.0.0.1");//支付客户端的IP地址（这里没做记录）
        param.put("notify_url", callbackUrl);
        param.put("trade_type", "NATIVE");//交易类型
        System.out.println("==================方法：createNative===== 参数map的值： " + param.toString());
        try {
            //根据appkey来生成签名，并同时将参数进行转换为xml格式
            String xmlParam = WXPayUtil.generateSignedXml(param, api_key);
            System.out.println("请求的参数：" + xmlParam);

            //2.发送请求（按照官方接口要求，将数据以post请求方式发送）
            HttpClient httpClient = new HttpClient("https://api.mch.weixin.qq.com/pay/unifiedorder");
            httpClient.setHttps(true);//以https的协议发送请求
            httpClient.setXmlParam(xmlParam);//设置post请求的参数列表
            httpClient.post();

            //3.获取结果
            String xmlResult = httpClient.getContent();

            Map<String, String> mapResult = WXPayUtil.xmlToMap(xmlResult);
            /*
                成功调用 支付接口后，返回的结果集：
               {nonce_str=lP5hZaU177mb62x0, code_url=weixin://wxpay/bizpayurl?pr=rBcrH5R, appid=wx632c8f211f8122c6,
                sign=9214719DDA317BEB0D836A9C194ACAC1, trade_type=NATIVE, return_msg=OK, result_code=SUCCESS, mch_id=1497984412, return_code=SUCCESS, prepay_id=wx1211363337481786f1e530461371971100}
                核心参数：code_url ： 生成支付二维码的地址

             */
            System.out.println("微信返回结果" + mapResult);
            //将返回的结果转换为对象
            WeixinPayResult weixinPayResult = new WeixinPayResult();
            //防止进行bean复制时，日期为null时报错
            ConvertUtils.register(new DateConverter(null), Date.class);
            BeanUtils.copyProperties(weixinPayResult, mapResult);
            //注意：付款订单编号是后台动态生成，必须要手动添加到返回结果中  勿忘，切记！！！
            weixinPayResult.setOut_trade_no(out_trade_no);
            return weixinPayResult;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 根据订单号查询订单状态
     *
     * @param app_id
     * @param mch_id
     * @param api_key
     * @param out_trade_no
     * @return
     */
    public static WeixinPayResult queryPayStatus(String app_id, String mch_id, String api_key, String out_trade_no) {
        Map resultMap = new HashMap();
        //1.封装参数
        Map param = new HashMap();
        param.put("appid", app_id);//appid
        param.put("mch_id", mch_id);//商户ID
        param.put("out_trade_no", out_trade_no);//要查询的订单号（自己系统所生成订单号）
        param.put("nonce_str", WXPayUtil.generateNonceStr());
        try {
            String xmlParam = WXPayUtil.generateSignedXml(param, api_key);
            //2.发送请求
            HttpClient httpClient = new HttpClient("https://api.mch.weixin.qq.com/pay/orderquery");
            httpClient.setHttps(true);
            httpClient.setXmlParam(xmlParam);
            httpClient.post();

            //3.获取结果
            String xmlResult = httpClient.getContent();
            Map<String, String> mapResult = WXPayUtil.xmlToMap(xmlResult);
            //封装结果数据
            System.out.println("调动查询API返回结果：" + xmlResult);
            WeixinPayResult weixinPayResult = new WeixinPayResult();
            //防止进行bean复制时，日期为null时报错
            ConvertUtils.register(new DateConverter(null), Date.class);
            BeanUtils.copyProperties(weixinPayResult, mapResult);
            return weixinPayResult;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }

    }

    /**
     * 关闭订单
     *
     * @param app_id
     * @param mch_id
     * @param api_key
     * @param out_trade_no
     * @return
     */
    public static WeixinPayResult closePay(String app_id, String mch_id, String api_key, String out_trade_no) {
        //1.封装参数
        Map param = new HashMap();
        param.put("appid", app_id);
        param.put("mch_id", mch_id);
        param.put("out_trade_no", out_trade_no);
        param.put("nonce_str", WXPayUtil.generateNonceStr());
        try {
            String xmlParam = WXPayUtil.generateSignedXml(param, api_key);
            //2.发送请求
            HttpClient httpClient = new HttpClient("https://api.mch.weixin.qq.com/pay/closeorder");
            httpClient.setHttps(true);
            httpClient.setXmlParam(xmlParam);
            httpClient.post();

            //3.获取结果
            String xmlResult = httpClient.getContent();
            Map<String, String> map = WXPayUtil.xmlToMap(xmlResult);
            System.out.println("调动查询API返回结果：" + xmlResult);
            WeixinPayResult weixinPayResult = new WeixinPayResult();
            //防止进行bean复制时，日期为null时报错
            ConvertUtils.register(new DateConverter(null), Date.class);
            BeanUtils.copyProperties(weixinPayResult, map);
            return weixinPayResult;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 微信红包发送公共方法
     *
     * @param app_id
     * @param mch_billno
     * @param mch_id
     * @param api_key
     * @param re_openid
     * @param total_amount 单位：分
     * @return
     */
    public static WeixinPayResult weixinRedPacket(String app_id, String mch_billno, String mch_id, String api_key, String re_openid, Integer total_amount) {
        //1.参数封装
        //下面的参数可以通过封装一个实体类的bean对象，同时返回的结果，也可以封装的一个bean对象
        Map param = new HashMap();
        param.put("nonce_str", WXPayUtil.generateNonceStr());//随机字符串
        param.put("mch_billno", mch_billno);//商户订单号
        param.put("mch_id", mch_id);//商户
        param.put("wxappid", app_id);//公众账号appid
        param.put("send_name", "筋斗云电商");//商户名称
        param.put("re_openid", re_openid);//用户openid
        param.put("total_amount", total_amount.toString());//红包金额（单位：分）
        param.put("total_num", "1");//红包发放总人数
        param.put("wishing", "恭喜，获取推广收益");//红包祝福语
        param.put("client_ip", "0.0.0.0");//ip地址
        param.put("act_name", "推广收益");//活动名称
        param.put("remark", "请在24小时内领取");//备注
        String sign = RedPackageSignUtil.redEnvelopeSign(param, api_key);
        param.put("sign", sign);
        try {
            //根据appkey来生成签名，并同时将参数进行转换为xml格式
            String xmlParam = WXPayUtil.mapToXml(param);
            System.out.println("请求的参数：" + xmlParam);
            String ssl = RedPackageSignUtil.ssl("https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack", mch_id, xmlParam);
            Map<String, String> mapResult = WXPayUtil.xmlToMap(ssl);
            WeixinPayResult weixinPayResult = new WeixinPayResult();
            //防止进行bean复制时，日期为null时报错
            ConvertUtils.register(new DateConverter(null), Date.class);
            BeanUtils.copyProperties(weixinPayResult, mapResult);
            return weixinPayResult;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 企业付款到用户零钱（不需要用户确认收钱）
     *
     * @param app_id
     * @param mch_id
     * @param api_key
     * @param partner_trade_no
     * @param openid
     * @param check_name
     * @param amount
     * @return
     */
    public static WeixinPayResult bussinessPayToChange(
            String app_id, String mch_id, String api_key, String partner_trade_no, String openid, String check_name, Integer amount) {
        //1.参数封装
        //下面的参数可以通过封装一个实体类的bean对象，同时返回的结果，也可以封装的一个bean对象
        Map param = new HashMap();
        param.put("mch_appid", app_id);//公众账号appid
        param.put("mchid", mch_id);//商户
        param.put("nonce_str", WXPayUtil.generateNonceStr());//随机字符串
        param.put("partner_trade_no", partner_trade_no);//商户订单号
        param.put("openid", openid);//用户openid
        param.put("check_name", "FORCE_CHECK");
        param.put("re_user_name", check_name);
        param.put("amount", amount.toString());//红包金额（单位：分）
        param.put("desc", "您的帐户提现");//备注
        param.put("spbill_create_ip", "0.0.0.0");//ip地址

        String sign = RedPackageSignUtil.redEnvelopeSign(param, api_key);
        param.put("sign", sign);
        try {
            //根据appkey来生成签名，并同时将参数进行转换为xml格式
            String xmlParam = WXPayUtil.mapToXml(param);
            System.out.println("请求的参数：" + xmlParam);
            String ssl = RedPackageSignUtil.ssl("https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers", mch_id, xmlParam);
            Map<String, String> mapResult = WXPayUtil.xmlToMap(ssl);
            WeixinPayResult weixinPayResult = new WeixinPayResult();
            //防止进行bean复制时，日期为null时报错
            ConvertUtils.register(new DateConverter(null), Date.class);
            BeanUtils.copyProperties(weixinPayResult, mapResult);
            return weixinPayResult;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}
